# -*- coding: utf-8 -*-

from fastapi import FastAPI, HTTPException, UploadFile, File, Form, Query, Request, BackgroundTasks
from fastapi.responses import HTMLResponse, JSONResponse, FileResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import Optional, List, Dict, Any
import asyncio
import aiofiles
import os
import json
import uuid
from datetime import datetime
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import threading
import time
from prompt_manager import PromptManager
from models import PromptItem, Category
from werkzeug.utils import secure_filename

# FastAPI应用初始化
app = FastAPI(
    title="提示词管理系统",
    description="基于FastAPI的异步提示词管理系统",
    version="2.0.0",
    docs_url="/docs",
    redoc_url="/redoc"
)

# CORS中间件
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# 模板和静态文件
templates = Jinja2Templates(directory="templates")

# 配置
UPLOAD_FOLDER = 'uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

# 初始化提示词管理器
manager = PromptManager()

# Pydantic模型
class PromptCreate(BaseModel):
    title: str
    content: str
    tags: Optional[List[str]] = []
    category_id: Optional[str] = "default"
    enabled: bool = True

class PromptUpdate(BaseModel):
    title: Optional[str] = None
    content: Optional[str] = None
    tags: Optional[List[str]] = None
    category_id: Optional[str] = None
    enabled: Optional[bool] = None

class CategoryCreate(BaseModel):
    name: str
    description: Optional[str] = None
    color: Optional[str] = None

class CategoryUpdate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    color: Optional[str] = None
    enabled: Optional[bool] = None

class AsyncImportData(BaseModel):
    title: str
    content: str

class AsyncSearchData(BaseModel):
    query: str
    category_id: Optional[str] = None
    limit: int = 10

class VariableReplaceData(BaseModel):
    variables: Dict[str, str]

# 热重载配置
class HotReloadHandler(FileSystemEventHandler):
    """文件变化监听器"""
    def __init__(self, callback):
        self.callback = callback
        self.last_modified = {}
        
    def on_modified(self, event):
        if event.is_directory:
            return
            
        # 只监听Python文件和模板文件
        if not (event.src_path.endswith('.py') or event.src_path.endswith('.html')):
            return
            
        # 防止重复触发
        current_time = time.time()
        if event.src_path in self.last_modified:
            if current_time - self.last_modified[event.src_path] < 1:
                return
                
        self.last_modified[event.src_path] = current_time
        print(f"检测到文件变化: {event.src_path}")
        
        # 异步执行回调
        threading.Thread(target=self.callback, daemon=True).start()

async def reload_manager():
    """重新加载管理器"""
    global manager
    try:
        print("正在重新加载数据...")
        manager = PromptManager()
        print("数据重新加载完成")
    except Exception as e:
        print(f"重新加载失败: {e}")

# 启动文件监听
def start_file_watcher():
    """启动文件监听器"""
    def sync_reload():
        asyncio.run(reload_manager())
    
    event_handler = HotReloadHandler(sync_reload)
    observer = Observer()
    
    # 监听当前目录和数据目录
    observer.schedule(event_handler, '.', recursive=True)
    observer.schedule(event_handler, 'data', recursive=True)
    observer.schedule(event_handler, 'templates', recursive=True)
    
    observer.start()
    print("文件监听器已启动")
    return observer

# 异步任务管理
class AsyncTaskManager:
    """异步任务管理器"""
    def __init__(self):
        self.tasks = {}
        self.task_counter = 0
        
    async def create_task(self, coro, task_name: str = None) -> str:
        """创建异步任务"""
        self.task_counter += 1
        task_id = f"task_{self.task_counter}"
        
        if task_name:
            task_id = f"{task_name}_{self.task_counter}"
            
        # 创建任务
        task = asyncio.create_task(coro)
        self.tasks[task_id] = {
            'status': 'running',
            'task': task,
            'created_at': datetime.now().isoformat()
        }
        
        # 设置任务完成回调
        def task_done_callback(task):
            try:
                result = task.result()
                self.tasks[task_id] = {
                    'status': 'completed',
                    'result': result,
                    'created_at': self.tasks[task_id]['created_at'],
                    'completed_at': datetime.now().isoformat()
                }
            except Exception as e:
                self.tasks[task_id] = {
                    'status': 'failed',
                    'error': str(e),
                    'created_at': self.tasks[task_id]['created_at'],
                    'failed_at': datetime.now().isoformat()
                }
        
        task.add_done_callback(task_done_callback)
        return task_id
        
    def get_task_status(self, task_id: str) -> Dict[str, Any]:
        """获取任务状态"""
        task_info = self.tasks.get(task_id, {'status': 'not_found'})
        # 移除task对象，避免序列化问题
        return {k: v for k, v in task_info.items() if k != 'task'}
        
    def list_tasks(self) -> Dict[str, Dict[str, Any]]:
        """列出所有任务"""
        return {tid: {k: v for k, v in task.items() if k != 'task'} 
                for tid, task in self.tasks.items()}

# 初始化异步任务管理器
task_manager = AsyncTaskManager()

# 启动事件
@app.on_event("startup")
async def startup_event():
    """应用启动事件"""
    print("FastAPI应用启动中...")
    # 启动文件监听器
    app.state.observer = start_file_watcher()
    print("应用启动完成")

@app.on_event("shutdown")
async def shutdown_event():
    """应用关闭事件"""
    print("正在关闭应用...")
    if hasattr(app.state, 'observer'):
        app.state.observer.stop()
        app.state.observer.join()
    print("应用已关闭")

# 主页路由
@app.get("/", response_class=HTMLResponse, name="index")
async def index(request: Request):
    """主页"""
    stats = manager.get_statistics()
    return templates.TemplateResponse("index.html", {"request": request, "stats": stats})

@app.get("/async-demo", response_class=HTMLResponse, name="async_demo")
async def async_demo(request: Request):
    """异步功能演示页面"""
    return templates.TemplateResponse("async_demo.html", {"request": request})

# 提示词相关路由
@app.get("/prompts", response_class=HTMLResponse, name="prompts")
async def prompts_page(request: Request, 
                      query: str = Query("", description="搜索关键词"),
                      category: str = Query("", description="分类ID"),
                      tags: str = Query("", description="标签，逗号分隔"),
                      enabled_only: bool = Query(False, description="只显示启用的"),
                      disabled_only: bool = Query(False, description="只显示禁用的")):
    """提示词列表页面"""
    # 搜索提示词
    tag_list = [tag.strip() for tag in tags.split(',') if tag.strip()] if tags else None
    prompts = manager.search_prompts(
        query=query,
        category_id=category if category else None,
        tags=tag_list,
        enabled_only=enabled_only,
        disabled_only=disabled_only
    )
    
    # 获取分类和标签
    categories = manager.get_all_categories()
    all_tags = manager.get_all_tags()
    
    return templates.TemplateResponse("prompts.html", {
        "request": request,
        "prompts": prompts,
        "categories": categories,
        "all_tags": all_tags,
        "current_query": query,
        "current_category": category,
        "current_tags": tags,
        "enabled_only": enabled_only,
        "disabled_only": disabled_only
    })

@app.get("/prompts/add", response_class=HTMLResponse, name="add_prompt")
async def add_prompt_page(request: Request):
    """添加提示词页面"""
    categories = manager.get_all_categories()
    return templates.TemplateResponse("add_prompt.html", {"request": request, "categories": categories})

@app.post("/prompts/add")
async def add_prompt(prompt_data: PromptCreate):
    """添加提示词API"""
    try:
        prompt = manager.add_prompt(
            title=prompt_data.title,
            content=prompt_data.content,
            tags=prompt_data.tags,
            category_id=prompt_data.category_id,
            enabled=prompt_data.enabled
        )
        
        if prompt:
            return {"success": True, "message": "提示词添加成功", "prompt_id": prompt.id}
        else:
            raise HTTPException(status_code=400, detail="提示词添加失败")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/prompts/{prompt_id}/edit", response_class=HTMLResponse, name="edit_prompt")
async def edit_prompt_page(request: Request, prompt_id: str):
    """编辑提示词页面"""
    prompt = manager.get_prompt_by_id(prompt_id)
    if not prompt:
        raise HTTPException(status_code=404, detail="提示词不存在")
    
    categories = manager.get_all_categories()
    return templates.TemplateResponse("edit_prompt.html", {
        "request": request,
        "prompt": prompt,
        "categories": categories
    })

@app.put("/prompts/{prompt_id}")
async def update_prompt(prompt_id: str, prompt_data: PromptUpdate):
    """更新提示词API"""
    try:
        # 获取现有提示词
        existing_prompt = manager.get_prompt_by_id(prompt_id)
        if not existing_prompt:
            raise HTTPException(status_code=404, detail="提示词不存在")
        
        # 更新字段
        update_data = {}
        if prompt_data.title is not None:
            update_data['title'] = prompt_data.title
        if prompt_data.content is not None:
            update_data['content'] = prompt_data.content
        if prompt_data.tags is not None:
            update_data['tags'] = prompt_data.tags
        if prompt_data.category_id is not None:
            update_data['category_id'] = prompt_data.category_id
        if prompt_data.enabled is not None:
            update_data['enabled'] = prompt_data.enabled
        
        success = manager.update_prompt(prompt_id, **update_data)
        
        if success:
            return {"success": True, "message": "提示词更新成功"}
        else:
            raise HTTPException(status_code=400, detail="提示词更新失败")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.delete("/prompts/{prompt_id}", name="delete_prompt")
async def delete_prompt(prompt_id: str):
    """删除提示词API"""
    try:
        success = manager.delete_prompt(prompt_id)
        if success:
            return {"success": True, "message": "提示词删除成功"}
        else:
            raise HTTPException(status_code=400, detail="提示词删除失败")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/prompts/{prompt_id}/toggle", name="toggle_prompt")
async def toggle_prompt(prompt_id: str):
    """切换提示词启用状态"""
    try:
        success = manager.toggle_prompt_enabled(prompt_id)
        if success:
            return {"success": True, "message": "状态切换成功"}
        else:
            raise HTTPException(status_code=404, detail="提示词不存在")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/prompts/{prompt_id}/export", name="export_single_prompt")
async def export_single_prompt(prompt_id: str):
    """导出单个提示词"""
    try:
        prompt = manager.get_prompt_by_id(prompt_id)
        if not prompt:
            raise HTTPException(status_code=404, detail="提示词不存在")
        
        from datetime import datetime
        import tempfile
        import os
        import re
        
        # 生成文件名，清理特殊字符
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        # 清理文件名中的特殊字符
        safe_title = re.sub(r'[^\w\s-]', '', prompt.title).strip()
        safe_title = re.sub(r'[-\s]+', '-', safe_title)
        filename = f"prompt_{safe_title}_{timestamp}.json"
        
        # 创建临时文件
        temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False, encoding='utf-8')
        temp_path = temp_file.name
        temp_file.close()
        
        # 导出提示词
        success = manager.export_single_prompt(prompt_id, temp_path)
        if not success:
            os.unlink(temp_path)
            raise HTTPException(status_code=500, detail="导出失败")
        
        # 返回文件，添加适当的响应头
        from fastapi.responses import FileResponse
        response = FileResponse(
            path=temp_path,
            filename=filename,
            media_type='application/json',
            headers={
                "Content-Disposition": f"attachment; filename*=UTF-8''{filename}"
            }
        )
        
        # 设置回调函数在响应完成后删除临时文件
        def cleanup():
            try:
                os.unlink(temp_path)
            except:
                pass
        
        response.background = cleanup
        return response
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/prompts/{prompt_id}/use", response_class=HTMLResponse, name="use_prompt")
async def use_prompt_page(request: Request, prompt_id: str):
    """使用提示词页面"""
    try:
        prompt = manager.get_prompt_by_id(prompt_id)
        if not prompt:
            raise HTTPException(status_code=404, detail="提示词不存在")
        return templates.TemplateResponse("use_prompt.html", {"request": request, "prompt": prompt})
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/api/prompts/{prompt_id}/replace", name="replace_variables")
async def replace_variables(prompt_id: str, variables_data: dict):
    """替换变量API"""
    try:
        prompt = manager.get_prompt_by_id(prompt_id)
        if not prompt:
            raise HTTPException(status_code=404, detail="提示词不存在")
        
        content = prompt.content
        variables = variables_data.get('variables', {})
        
        # 替换变量
        for key, value in variables.items():
            content = content.replace(f"{{{{{key}}}}}", str(value))
        
        return {"success": True, "content": content}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/api/prompts/{prompt_id}/replace")
async def replace_variables(prompt_id: str, variable_data: VariableReplaceData):
    """替换变量API"""
    try:
        prompt = manager.get_prompt_by_id(prompt_id)
        if not prompt:
            raise HTTPException(status_code=404, detail="提示词不存在")
        
        result = prompt.replace_variables(variable_data.variables)
        
        return {
            "success": True,
            "result": result,
            "variables": prompt.variables or []
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# 分类相关路由
@app.get("/categories", response_class=HTMLResponse, name="categories")
async def categories_page(request: Request):
    """分类列表页面"""
    categories = manager.get_all_categories()
    
    # 为每个分类添加提示词数量
    for category in categories:
        category.prompt_count = manager.get_prompt_count_by_category(category.id)
    
    return templates.TemplateResponse("categories.html", {"request": request, "categories": categories})

@app.get("/categories/add", response_class=HTMLResponse, name="add_category")
async def add_category_page(request: Request):
    """添加分类页面"""
    return templates.TemplateResponse("add_category.html", {"request": request})

@app.post("/categories/add")
async def add_category(category_data: CategoryCreate):
    """添加分类API"""
    try:
        category = manager.add_category(
            name=category_data.name,
            description=category_data.description,
            color=category_data.color
        )
        
        if category:
            return {"success": True, "message": "分类添加成功", "category_id": category.id}
        else:
            raise HTTPException(status_code=400, detail="分类添加失败")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/categories/{category_id}/edit", response_class=HTMLResponse, name="edit_category")
async def edit_category_page(request: Request, category_id: str):
    """编辑分类页面"""
    category = manager.get_category_by_id(category_id)
    if not category:
        raise HTTPException(status_code=404, detail="分类不存在")
    
    return templates.TemplateResponse("edit_category.html", {
        "request": request,
        "category": category
    })

@app.put("/categories/{category_id}")
async def update_category(category_id: str, category_data: CategoryUpdate):
    """更新分类API"""
    try:
        # 获取现有分类
        existing_category = manager.get_category_by_id(category_id)
        if not existing_category:
            raise HTTPException(status_code=404, detail="分类不存在")
        
        # 更新字段
        update_data = {}
        if category_data.name is not None:
            update_data['name'] = category_data.name
        if category_data.description is not None:
            update_data['description'] = category_data.description
        if category_data.color is not None:
            update_data['color'] = category_data.color
        if category_data.enabled is not None:
            update_data['enabled'] = category_data.enabled
        
        success = manager.update_category(category_id, **update_data)
        
        if success:
            return {"success": True, "message": "分类更新成功"}
        else:
            raise HTTPException(status_code=400, detail="分类更新失败")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.delete("/categories/{category_id}")
async def delete_category(category_id: str):
    """删除分类API"""
    try:
        if category_id == 'default':
            raise HTTPException(status_code=400, detail="不能删除默认分类")
        
        success = manager.delete_category(category_id)
        if success:
            return {"success": True, "message": "分类删除成功"}
        else:
            raise HTTPException(status_code=400, detail="分类删除失败")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# 导入导出相关路由
@app.get("/import", response_class=HTMLResponse, name="import_prompts")
async def import_page(request: Request):
    """导入页面"""
    categories = manager.get_all_categories()
    return templates.TemplateResponse("import.html", {"request": request, "categories": categories})

@app.post("/import")
async def import_data(request: Request, import_mode: str = Form(...), file: UploadFile = File(None), json_content: str = Form(""), title: str = Form("")):
    """处理导入数据"""
    try:
        if import_mode == "file" and file:
            # 文件导入模式
            if not file.filename.lower().endswith('.json'):
                raise HTTPException(status_code=400, detail="只支持JSON格式文件")
            
            content = await file.read()
            try:
                content_str = content.decode('utf-8')
            except UnicodeDecodeError:
                try:
                    content_str = content.decode('gbk')
                except UnicodeDecodeError:
                    raise HTTPException(status_code=400, detail="文件编码不支持，请使用UTF-8或GBK编码")
            
            # 验证JSON格式
            try:
                json_data = json.loads(content_str)
            except json.JSONDecodeError as e:
                raise HTTPException(status_code=400, detail=f"JSON格式错误：{str(e)}")
            
            # 使用文件名作为标题
            import_title = file.filename.replace('.json', '') if file.filename else "导入的数据"
            formatted_content = json.dumps(json_data, ensure_ascii=False, indent=2)
            
        elif import_mode == "json_content" and json_content:
            # JSON内容导入模式
            try:
                json_data = json.loads(json_content)
            except json.JSONDecodeError as e:
                raise HTTPException(status_code=400, detail=f"JSON格式错误：{str(e)}")
            
            import_title = title if title else "编辑后的JSON数据"
            formatted_content = json.dumps(json_data, ensure_ascii=False, indent=2)
            
        else:
            raise HTTPException(status_code=400, detail="请选择文件或输入JSON内容")
        
        # 添加提示词
        prompt = manager.add_prompt(
            title=import_title,
            content=formatted_content,
            category_id='default',
            tags=['JSON导入'],
            enabled=True
        )
        
        if prompt:
            # 重定向到提示词列表页面，并显示成功消息
            return RedirectResponse(url="/prompts?import_success=1", status_code=303)
        else:
            raise HTTPException(status_code=400, detail="导入失败，请检查输入内容")
            
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"导入失败：{str(e)}")

@app.post("/import/json")
async def import_json_content(title: str = Form(...), json_content: str = Form(...)):
    """导入JSON内容"""
    try:
        # 验证JSON格式
        json_data = json.loads(json_content)
        
        # 格式化JSON内容
        formatted_content = json.dumps(json_data, ensure_ascii=False, indent=2)
        
        # 添加提示词
        prompt = manager.add_prompt(
            title=title,
            content=formatted_content,
            category_id='default',
            tags=['JSON导入', '已编辑'],
            enabled=True
        )
        
        if prompt:
            return {"success": True, "message": f'编辑后的JSON数据 "{title}" 导入成功！'}
        else:
            raise HTTPException(status_code=400, detail="导入失败，请检查输入内容")
            
    except json.JSONDecodeError as e:
        error_msg = f'JSON格式错误：第{e.lineno}行，第{e.colno}列 - {e.msg}'
        raise HTTPException(status_code=400, detail=error_msg)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f'导入失败：{str(e)}')

@app.post("/import/file")
async def import_file(file: UploadFile = File(...), title: str = Form("")):
    """导入文件"""
    try:
        # 检查文件扩展名
        if not file.filename.lower().endswith('.json'):
            raise HTTPException(status_code=400, detail="只支持JSON格式文件")
        
        # 读取文件内容
        content = await file.read()
        
        # 尝试不同编码
        try:
            content_str = content.decode('utf-8')
        except UnicodeDecodeError:
            content_str = content.decode('gbk')
        
        # 验证JSON格式
        json_data = json.loads(content_str)
        
        # 格式化JSON内容
        formatted_content = json.dumps(json_data, ensure_ascii=False, indent=2)
        
        # 使用用户输入的标题或文件名（不含扩展名）作为标题
        final_title = title.strip() if title.strip() else os.path.splitext(file.filename)[0]
        
        # 创建新的提示词
        prompt = manager.add_prompt(
            title=final_title,
            content=formatted_content,
            category_id='default',
            tags=['JSON导入'],
            enabled=True
        )
        
        if prompt:
            return {"success": True, "message": f'JSON文件 "{file.filename}" 导入成功！'}
        else:
            raise HTTPException(status_code=400, detail="导入失败，请检查文件内容")
            
    except json.JSONDecodeError as e:
        error_msg = f'JSON格式错误：第{e.lineno}行，第{e.colno}列 - {e.msg}'
        raise HTTPException(status_code=400, detail=error_msg)
    except Exception as e:
        raise HTTPException(status_code=500, detail=f'导入失败：{str(e)}')



@app.post("/backup", name="backup_data")
async def backup_data():
    """备份数据"""
    try:
        backup_file = manager.backup_data()
        if backup_file:
            return {"success": True, "message": f"数据备份成功: {backup_file}"}
        else:
            raise HTTPException(status_code=500, detail="数据备份失败")
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# 统计页面
@app.get("/stats", response_class=HTMLResponse, name="stats")
async def stats_page(request: Request):
    """统计页面"""
    stats = manager.get_statistics()
    return templates.TemplateResponse("stats.html", {"request": request, "stats": stats})

# API路由
@app.get("/api/search")
async def api_search(q: str = Query("", description="搜索关键词"),
                    category: str = Query("", description="分类ID"),
                    limit: int = Query(10, description="结果数量限制")):
    """搜索API"""
    try:
        prompts = manager.search_prompts(
            query=q,
            category_id=category if category else None,
            enabled_only=True
        )
        
        # 限制结果数量
        prompts = prompts[:limit]
        
        results = []
        for prompt in prompts:
            category_obj = manager.get_category_by_id(prompt.category_id)
            results.append({
                'id': prompt.id,
                'title': prompt.title,
                'content': prompt.content[:100] + '...' if len(prompt.content) > 100 else prompt.content,
                'tags': prompt.tags,
                'category': category_obj.name if category_obj else '未知',
                'variables': prompt.variables or []
            })
        
        return {
            'success': True,
            'results': results,
            'total': len(results)
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# 异步API路由
@app.post("/api/async/backup")
async def async_backup():
    """异步备份数据"""
    async def backup_task():
        await asyncio.sleep(0.1)  # 模拟异步操作
        try:
            backup_file = manager.backup_data()
            return {'success': True, 'backup_file': backup_file}
        except Exception as e:
            return {'success': False, 'error': str(e)}
    
    task_id = await task_manager.create_task(backup_task(), 'backup')
    return {
        'success': True,
        'task_id': task_id,
        'message': '备份任务已启动'
    }

@app.post("/api/async/import")
async def async_import(data: AsyncImportData):
    """异步导入数据"""
    async def import_task():
        await asyncio.sleep(0.1)  # 模拟异步操作
        try:
            # 模拟处理时间
            await asyncio.sleep(2)
            
            # 实际导入逻辑
            prompt = manager.add_prompt(
                title=data.title,
                content=data.content,
                tags=['异步导入'],
                category_id='default',
                enabled=True
            )
            
            if prompt:
                return {'success': True, 'message': '数据导入成功', 'prompt_id': prompt.id}
            else:
                return {'success': False, 'error': '导入失败'}
        except Exception as e:
            return {'success': False, 'error': str(e)}
    
    task_id = await task_manager.create_task(import_task(), 'import')
    return {
        'success': True,
        'task_id': task_id,
        'message': '导入任务已启动'
    }

@app.post("/api/async/search")
async def async_search(data: AsyncSearchData):
    """异步搜索"""
    async def search_task():
        await asyncio.sleep(0.1)  # 模拟异步操作
        try:
            # 模拟复杂搜索处理
            await asyncio.sleep(1)
            
            prompts = manager.search_prompts(query=data.query)
            results = []
            
            for prompt in prompts[:data.limit]:
                category = manager.get_category_by_id(prompt.category_id) if prompt.category_id else None
                results.append({
                    'id': prompt.id,
                    'title': prompt.title,
                    'content': prompt.content[:200] + '...' if len(prompt.content) > 200 else prompt.content,
                    'tags': prompt.tags,
                    'category': category.name if category else '未知',
                    'created_at': prompt.created_at.isoformat() if prompt.created_at else None
                })
            
            return {'success': True, 'results': results, 'total': len(results)}
        except Exception as e:
            return {'success': False, 'error': str(e)}
    
    task_id = await task_manager.create_task(search_task(), 'search')
    return {
        'success': True,
        'task_id': task_id,
        'message': '搜索任务已启动'
    }

@app.get("/api/tasks/{task_id}")
async def get_task_status(task_id: str):
    """获取任务状态"""
    status = task_manager.get_task_status(task_id)
    return status

@app.get("/api/tasks")
async def list_tasks():
    """列出所有任务"""
    tasks = task_manager.list_tasks()
    return tasks

@app.post("/api/reload")
async def manual_reload():
    """手动重新加载数据"""
    try:
        await reload_manager()
        return {'success': True, 'message': '数据重新加载成功'}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# 错误处理
@app.exception_handler(404)
async def not_found_handler(request: Request, exc: HTTPException):
    return templates.TemplateResponse("404.html", {"request": request}, status_code=404)

@app.exception_handler(500)
async def internal_error_handler(request: Request, exc: HTTPException):
    return templates.TemplateResponse("500.html", {"request": request}, status_code=500)

if __name__ == "__main__":
    import uvicorn
    
    print("启动FastAPI应用 (支持热重载)...")
    print("访问地址: http://localhost:8888")
    print("API文档: http://localhost:8888/docs")
    print("按 Ctrl+C 停止服务")
    
    uvicorn.run(
        "fastapi_app:app",
        host="0.0.0.0",
        port=8888,
        reload=True,
        reload_dirs=[".", "templates", "data"],
        reload_includes=["*.py", "*.html", "*.json"]
    )